﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.MainModule.Customers;
using Domain.MainModule.Entities;
using Domain.Core;
using Domain.Core.Specification;

namespace Application.MainModule.CustomersManagement
{
    public class CustomerManagementService: ICustomerManagementService
    {
                #region Members

        ICustomerRepository _CustomerRepository;

        #endregion

        #region Constructor

        /// <summary>
        /// Default constructor for CustomerService
        /// </summary>
        /// <param name="customerRepository">CustomerRepository dependency, usually this is resolver with IoC</param>
        public CustomerManagementService(ICustomerRepository customerRepository)
        {
            if (customerRepository == (ICustomerRepository)null)
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);

            _CustomerRepository = customerRepository;
        }

        #endregion

        public void AddCustomer(Customer customer)
        {
            if (customer.UserId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidUserId, "customer.UserId");

            customer.UserId = Guid.NewGuid();

            IUnitOfWork unitOfWork = _CustomerRepository.UnitOfWork as IUnitOfWork;
            _CustomerRepository.Add(customer);
            unitOfWork.Commit();
        }

        public void ChangeCustomer(Customer customer)
        {
            IUnitOfWork unitOfWork = _CustomerRepository.UnitOfWork as IUnitOfWork;
            _CustomerRepository.Modify(customer);
            unitOfWork.CommitAndRefreshChanges();
        }

        public void RemoveCustomer(Customer customer)
        {
            if (customer == (Customer)null)
                throw new ArgumentNullException("customer");

            IUnitOfWork unitOfWork = _CustomerRepository.UnitOfWork as IUnitOfWork;
            customer.IsEnabled = false;
            _CustomerRepository.Modify(customer);
            unitOfWork.CommitAndRefreshChanges();
        }

        public List<Customer> FindPagedCustomers(int pageIndex, int pageCount)
        {
            if (pageIndex < 0)
                throw new ArgumentException(Resources.Messages.exception_InvalidPageIndex, "pageIndex");

            if (pageCount <= 0)
                throw new ArgumentException(Resources.Messages.exception_InvalidPageCount, "pageCount");

            bool enabled = true;
            Specification<Customer> onlyEnabledSpec = new DirectSpecification<Customer>(c => c.IsEnabled == enabled);

            return _CustomerRepository.GetPagedCustomers(pageIndex, pageCount).ToList();

        }

        public Customer FindCustomerByUserId(Guid userId)
        {
            if (userId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidUserId, "customer.UserId");

            CustomerMembershipUserIdSpecification spec = new CustomerMembershipUserIdSpecification(userId);
            return _CustomerRepository.FindCustomer(spec);
        }

        public Customer FindCustomerById(Guid customerId)
        {
            if (customerId == null)
                throw new ArgumentNullException(Resources.Messages.exception_InvalidUserId, "customerId");

            CustomerCustomerIdSpecification spec = new CustomerCustomerIdSpecification(customerId);
            return _CustomerRepository.FindCustomer(spec);
        }

        #region IDisposable

        /// <summary>
        /// Dispose associated context with this domain service
        /// </summary>
        public void Dispose()
        {
            if (_CustomerRepository != null
                &&
                _CustomerRepository.UnitOfWork != null)
            {
                _CustomerRepository.UnitOfWork.Dispose();
            }
        }

        #endregion

    }
}
